﻿using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using LogikBug.ModularMvc.Navigation;
using LogikBug.ModularMvc.Properties;

namespace LogikBug.ModularMvc
{
	public static class HtmlHelperExtensions
	{
		#region Methods

		public static MvcHtmlString ModulePartial(this HtmlHelper htmlHelper, string partialName)
		{
			return htmlHelper.Partial(partialName);
		}

		public static MvcHtmlString ModulePartial(this HtmlHelper htmlHelper, string partialName, bool searchModules)
		{
			if (!searchModules)
			{
				return htmlHelper.Partial(partialName);
			}

			var result = MvcHtmlString.Empty;
			var currentContext = ModularHttpContext.Current;
			var currentModule = currentContext.Module;
			var provider = currentModule != null ? currentModule.Provider : ModuleProvider.Current;

			foreach (var module in provider.OfType<IModule>())
			{
				result = htmlHelper.ModulePartialInternal(currentContext, partialName, module.Key, false);

				if (!MvcHtmlString.IsNullOrEmpty(result))
				{
					break;
				}
			}

			currentContext.Module = currentModule;

			return result;
		}

		public static MvcHtmlString ModulePartial(this HtmlHelper htmlHelper, string partialName, object moduleKey)
		{
			return ModulePartial(htmlHelper, partialName, moduleKey, false);
		}

		public static MvcHtmlString ModulePartial(this HtmlHelper htmlHelper, string partialName, object moduleKey, bool throwIfNotFound)
		{
			return htmlHelper.ModulePartialInternal(ModularHttpContext.Current, partialName, moduleKey, false);
		}

		private static MvcHtmlString ModulePartialInternal(this HtmlHelper htmlHelper, ModularHttpContext modularContext, string partialName, object moduleKey, bool throwIfNotFound)
		{
			var result = MvcHtmlString.Empty;
			var provider = modularContext.Module != null ? modularContext.Module.Provider : ModuleProvider.Current;
			var module = provider[moduleKey];

			if (module == null && throwIfNotFound)
			{
				throw new InvalidOperationException(string.Format(Resources.PartialViewNotFoundInModuleFormat, partialName, moduleKey));
			}

			if (module != null && module.IsEnabled)
			{
				var currentModule = modularContext.Module;
				modularContext.Module = module;

				try
				{
					result = htmlHelper.Partial(partialName);
				}
				catch (Exception e)
				{
					if (throwIfNotFound)
					{
						throw new InvalidOperationException(string.Format(Resources.PartialViewNotFoundInModuleFormat, partialName, moduleKey), e);
					}
				}

				modularContext.Module = currentModule;
			}

			return result;
		}

		public static MvcHtmlString RenderModuleMenus(this HtmlHelper htmlHelper)
		{
			return htmlHelper.RenderModuleMenus(MenuType.Main);
		}

		public static MvcHtmlString RenderModuleMenus(this HtmlHelper htmlHelper, MenuType menuType)
		{
			var module = ModularHttpContext.Current.Module;
			var provider = (module != null) ? module.Provider : ModuleProvider.Current;
			return provider.GenerateMenu(htmlHelper.ViewContext, menuType);
		}

		#endregion
	}
}
